home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -in_the_mag- / new_music / zms_kocmu3 / orig-tb.c < prev    next >
C/C++ Source or Header  |  1999-06-18  |  5KB  |  229 lines

  1. /*
  2.  * tb.c - Roland TB303 Emulator
  3.  * Lars Hamre, 1995
  4.  *
  5.  * Compiles with: sc tb.c link math=68881
  6.  * Usage: tb >ram:sample
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12.  
  13. /*
  14.  *   1  3     6  8 10    13 15    18 20 22    25 27    30 32 34
  15.  *   c  d     f  g  a     c  d     f  g  a     c  d     f  g  a
  16.  *  C  D  E  F  G  A  B  C  D  E  F  G  A  B  C  D  E  F  G  A  B  C
  17.  *  0  2  4  5  7  9 11 12 14 16 17 19 21 23 24 26 28 29 31 33 35 36
  18.  */
  19.  
  20. char Note[16]=
  21. {
  22.     24,23,19,17,19, 7,21,22, 10,20, 8,18,17,8,20,12
  23. };
  24.  
  25. /*
  26.  * 0 = rest
  27.  * 1 = 16th note
  28.  * 2 = tie
  29.  */
  30.  
  31. char NoteLength[16]=
  32. {
  33.     1,1,1,1,1,1,1,1, 2,1,1,1,2,1,1,1
  34. };
  35.  
  36. /*
  37.  * 0 = no accent
  38.  * 1 = accent on
  39.  *
  40.  * Accent is not used yet, but increases volume and resonance
  41.  */
  42.  
  43. char Accent[16] =
  44. {
  45.     0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
  46. };
  47.  
  48. /*
  49.  * 0 = go instantly to the next note
  50.  * 1 = slide to the new note
  51.  */
  52.  
  53. char Slide[16] =
  54. {
  55.     0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
  56. };
  57.  
  58. /*
  59.  * This program is a mess of strange variable names and commented out code, but
  60.  * it sort of works. It's only something to experiment with.
  61.  */
  62.  
  63. void main(void)
  64. {
  65.     int tot=0, out, notenum=0;
  66.     float vco2 = 0, vco = 1.0;
  67.     float vcophase=0;
  68.     float vcofreq = 1, lastvcofreq=0, vcoadd, vcofreq2=0;
  69.     float hig=0, mid=0, low=0, freq = 0;
  70.     float hig2=0, mid2=0, low2=0;
  71.  
  72.     // Note: resonance is "backwards" in this type of filter, so a low
  73.     // value is max resonance. 
  74.  
  75.     float reso = 0.05;
  76.     float feedbk, flevel=0.01;
  77.     float amp = 0.0, inp;
  78.     int emode = 2;
  79.     //while (tot < 39147)
  80.     while (tot < 90000)
  81.     //while (tot < 32000)
  82.     {
  83.  
  84. //---------- VCO ----------
  85. // The squarewave rises faster than is falls, and that means that the
  86. // rising edge is sharper and will have more resonance. I guess it is
  87. // caused by the VCO being an integrator with a reset circuit for the
  88. // sawtooth wave, and the squarewave is simply a "hard limited" version
  89. // of the saw by feeding it through an op-amp comparator. This simulation
  90. // only does squarewave, but a sawtooth would be: vcophase/128 - 1.
  91.  
  92.         if (vco > 0)
  93.             vco2 = vco2 + (vco - vco2) * 0.95;
  94.         else
  95.         //      vco2 = vco2 + (vco - vco2) * 0.2;
  96.             vco2 = vco2 + (vco - vco2) * 0.9;
  97.  
  98. // Highpass filter to get the "falling down to zero" look.
  99. // This is probably not what really happens, because the 303 has lots of
  100. // bass output - so I guess it is caused by the filter. It is just a hack
  101. // to make the waveform look more like the original. I need a 303 sample
  102. // without resonance!
  103. //        {
  104. //            static float delta=0;
  105. //            delta += vco2;
  106. //            delta = delta * 0.99;
  107. //            inp = delta;
  108. //            delta -= vco2;
  109. //        }
  110.  
  111.         inp = vco2;
  112.  
  113. // Update VCO phase
  114.  
  115.         if (Slide[notenum])
  116.             vcofreq2 = vcofreq2 + (vcofreq - vcofreq2) * 0.002;
  117.         else
  118.             vcofreq2 = vcofreq;
  119.         if (vcofreq2 != lastvcofreq)
  120.             vcoadd = pow(2.0, vcofreq2 - 0.37);
  121.         //      vcoadd = pow(2.0, vcofreq2 + 0.35);
  122.         lastvcofreq = vcofreq2;
  123.         vcophase += vcoadd;
  124.         if (vcophase >= 256)
  125.         {
  126.             vcophase -= 256;
  127.             vco = - vco;
  128.         }
  129.         if ((tot % 2000) == 0)
  130.         {
  131.             vcofreq = Note[notenum] / 12.0;
  132.         }
  133.  
  134. //---------- VCF ----------
  135.  
  136.         // Initial cutoff freq + envelope amount
  137.         freq = 0.08 + 0.8*amp;
  138.         //reso *= 0.99995;
  139.         feedbk = reso*mid;
  140.  
  141.         /**** Useless (?) hack to simulate diode limiting of resonance ****/
  142.         if (feedbk >flevel)
  143.         {
  144.             float sq = (feedbk-flevel)*2.0;
  145.             feedbk += sq*sq;
  146.         }
  147.         else if (feedbk < -flevel)
  148.         {
  149.             float sq = (feedbk+flevel)*2.0;
  150.             feedbk -= sq*sq;
  151.         }
  152.  
  153.         /******************************************************************/
  154.         // 2 pole filter #1
  155.  
  156.         hig = inp - feedbk - low;
  157.         mid += hig * freq;
  158.         low += mid * freq;
  159.  
  160.         // 2 pole filter #2
  161.         hig2 = low - 1*mid2 - low2;
  162.         mid2 += hig2 * freq;
  163.         low2 += mid2 * freq;
  164.  
  165. //---------- VCA ----------
  166.  
  167.         // Trig envelope attack
  168.         if ((tot % 2000) == 0)
  169.             if (NoteLength[notenum] == 1)
  170.                 emode = 0;
  171.  
  172.         // Trig envelope release
  173.         if ((tot % 2000) == 1100)
  174.             if (NoteLength[(notenum+1)%16] != 2)
  175.                 emode = 2;
  176.         switch (emode)
  177.         {
  178.             case 0:
  179.                 // Attack state
  180.                 // Capacitor charge attack...
  181.                 //amp = amp + (1.1 - amp) * 0.01;
  182.  
  183.                 // ... but the TB303 attack looks more like this
  184.  
  185.                 amp = amp*1.1 + 0.01;
  186.                 if (amp >= 1.0)
  187.                 {
  188.                     amp = 1.0;
  189.                     emode = 1;
  190.                 }
  191.                 break;
  192.             // Decay state - tweak as you like
  193.             case 1:
  194.                 amp = amp * 0.9998;
  195.                 break;
  196.             // Release state
  197.             case 2:
  198.                 amp = amp * 0.99;
  199.                 break;
  200.         }
  201.         // Output is lowpass (try low or low2) multiplied by amplitude.
  202.         // 40 seems like a nice value to avoid clipping with lots of
  203.         // resonance.
  204.         out = low * amp * 40;
  205.  
  206. //-------- Output ----------
  207.  
  208.         // Clip to min/max values
  209.         // Easy to tweak to 16 bit output instead of 8
  210.  
  211.         if (out > 127)
  212.             out = 127;
  213.         if (out < -128)
  214.             out = -128;
  215.         putc(out,stdout);
  216.         tot++;
  217.  
  218. //------------------------
  219.  
  220.         // At the end of a note, start another one
  221.         if ((tot % 2000) == 1999)
  222.         {
  223.             notenum++;
  224.             if (notenum >= 16)
  225.                 notenum = 0;
  226.         }
  227.     }
  228. }
  229.